package main

import (
	"bufio"
	"crypto/tls"
	"database/sql"
	"encoding/csv"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"llm-flow/asset"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/gorilla/websocket"
	"github.com/tealeg/xlsx"
)

const (
	// 设置WebSocket读写超时时间
	wsReadTimeout  = 10 * time.Second
	wsWriteTimeout = 10 * time.Second
)

var (
	DB            *sql.DB
	HOME          string
	SESSIONS_HOME string
	STATIC        string
	agentPath     string
)

type NetMessage struct {
	Id      string         `json:"id"`
	Remote  string         `json:"remote"`
	Data    map[string]any `json:"data"`
	Type    string         `json:"type"`
	Headers map[string]any `json:"headers"`
	Stream  bool           `json:"stream"`
	Usepost bool           `json:"usepost"`
	Cookie  string         `json:"cookie"`
}
type Session struct {
	UserName    string
	SessionData map[string]any
}

func GetSession(name string) (sess *Session) {
	path := filepath.Join(SESSIONS_HOME, name+".json")
	buffer, err := os.ReadFile(path)
	if err != nil {
		return nil
	}
	sess = &Session{
		UserName:    name,
		SessionData: map[string]any{},
	}
	json.Unmarshal(buffer, &sess.SessionData)
	return
}

func (sess *Session) SaveSession() {
	if sess == nil {
		fmt.Println("no session data!")
		return
	}
	fpath := filepath.Join(SESSIONS_HOME, sess.UserName+".json")
	if buf, err := json.Marshal(sess.SessionData); err == nil {
		os.WriteFile(fpath, buf, os.ModePerm)
	} else {
		fmt.Println("invalid session data!")
	}
}

func main() {

	var err error
	HOME, err = os.UserHomeDir()
	if err != nil {
		log.Fatal(err)
	}
	SESSIONS_HOME = filepath.Join(HOME, ".cache", "llm-flow-sessions")
	agentPath = filepath.Join(HOME, ".cache", "agents")
	STATIC = os.TempDir()
	os.Mkdir(SESSIONS_HOME, os.ModePerm)
	// 注册路由处理函数

	serveMux := http.NewServeMux()
	for _, name := range asset.AssetNames() {
		fname := strings.TrimPrefix(name, "dist")
		fmt.Println(fname)
		if fname == "/index.html" {
			fname = "/"
		}
		serveMux.HandleFunc(fname, func(w http.ResponseWriter, r *http.Request) {
			if fname == "/" {
				w.Header().Set("content-type", "text/html")
			} else if strings.HasSuffix(fname, ".js") {
				w.Header().Set("content-type", "text/javascript")
			} else if strings.HasSuffix(fname, ".css") {
				w.Header().Set("content-type", "text/css")
			}
			if buf, err := asset.Asset(name); err != nil {
				w.Write([]byte(err.Error()))
			} else {
				w.Write(buf)
			}
		})

	}

	// serveMux.Handle("/socket.io/", socketioHandler)
	serveMux.HandleFunc("/get_sessions", getSessions)
	serveMux.HandleFunc("/save_session", saveSession)
	serveMux.HandleFunc("/v1/chat/completions", chatCompletionsHandler)
	serveMux.HandleFunc("/socket.io", websocketHandler)
	serveMux.HandleFunc("/down_me/", downloadFileHandler)
	serveMux.HandleFunc("/down_results", getDownURLHandler)
	serveMux.HandleFunc("/upload", uploadHandler)
	serveMux.HandleFunc("/list_agent", listAgentHandler)
	serveMux.HandleFunc("/load_agent", loadAgent)
	serveMux.HandleFunc("/del_agent", delAgent)
	serveMux.HandleFunc("/save_agent", saveAgent)
	serveMux.HandleFunc("/get_preview", getPreivew)
	port := os.Getenv("PORT")
	if port == "" {
		port = "7778"
	}
	fmt.Println(":" + port)
	http.ListenAndServe(":"+port, serveMux)
}

type Event struct {
	Data  string
	Event string
	Id    string
	Retry int
}

func parseEventStream(body io.Reader) <-chan Event {
	events := make(chan Event)
	scanner := bufio.NewScanner(body)
	var currentEvent Event
	go func() {
		defer close(events)
		for scanner.Scan() {
			line := scanner.Text()
			if line == "" {
				if currentEvent.Data != "" || currentEvent.Event != "" || currentEvent.Id != "" {
					events <- currentEvent
					currentEvent = Event{}
				}
				continue
			}
			if strings.HasPrefix(line, "data:") {
				currentEvent.Data += strings.TrimPrefix(line, "data: ") + "\n"
			} else if strings.HasPrefix(line, "event:") {
				currentEvent.Event = strings.TrimPrefix(line, "event: ")
			} else if strings.HasPrefix(line, "id:") {
				currentEvent.Id = strings.TrimPrefix(line, "id: ")
			} else if strings.HasPrefix(line, "retry:") {
				retry, _ := strconv.Atoi(strings.TrimPrefix(line, "retry: "))
				currentEvent.Retry = retry
			}
		}
		if currentEvent.Data != "" || currentEvent.Event != "" || currentEvent.Id != "" {
			events <- currentEvent
		}
	}()
	return events
}

func chatCompletionsHandler(w http.ResponseWriter, r *http.Request) {

	// 目标URL
	targetURL := "https://115.236.8.156:6404/v1/chat/completions"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	// 创建新的请求
	req, err := http.NewRequest("POST", targetURL, r.Body)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	// 复制请求头
	for key, values := range r.Header {
		req.Header[key] = values
	}

	// 复制查询参数
	req.URL.RawQuery = r.URL.RawQuery

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("err:", err)
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}
	defer resp.Body.Close()

	// 检查状态码
	if resp.StatusCode != http.StatusOK {
		http.Error(w, "Request failed", resp.StatusCode)
		return
	}

	// 设置响应头
	// w.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")

	for line := range parseEventStream(resp.Body) {
		if line.Data != "" && line.Data != "[DONE]" {
			w.Write([]byte("data: " + line.Data + "\n"))
			w.(http.Flusher).Flush()
		} else if line.Data == "[DONE]" {
			w.Write([]byte("[DONE]"))
		}

		// 模拟事件生成间隔

	}
}

// 获取用户ID的函数，假设通过某种方式获取，例如从请求头或cookie
func getUserID(r *http.Request) (name string, err error) {
	// 这里需要根据实际需求实现，例如从请求头获取用户ID
	// 例如，从请求头中获取用户ID
	c, err := r.Cookie("user_name")
	if err != nil {
		return "", err
	}
	if c.Value == "" {
		return "", fmt.Errorf("no user !")
	}

	return c.Value, nil
}

// /get_sessions路由处理函数
func getSessions(w http.ResponseWriter, r *http.Request) {
	user_id, err := getUserID(r)
	if err != nil {
		http.Error(w, "Invalid User ID", http.StatusBadRequest)
		return
	}
	sess := GetSession(user_id)
	if sess == nil {
		http.Error(w, "User ID is required", http.StatusBadRequest)
		return
	}

	// 返回JSON响应
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(map[string]interface{}{
		"sessions": sess.SessionData,
	}); err != nil {
		http.Error(w, "JSON encoding error", http.StatusInternalServerError)
	}
}

// /save_session路由处理函数
func saveSession(w http.ResponseWriter, r *http.Request) {
	// 解析JSON请求体
	var chats map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&chats); err != nil {
		http.Error(w, "Invalid JSON", http.StatusBadRequest)
		return
	}
	defer r.Body.Close()

	user_id, err := getUserID(r)

	if err != nil {
		http.Error(w, "Invalid User ID", http.StatusBadRequest)
		return
	}
	if user_id == "" {
		http.Error(w, "User ID is required", http.StatusBadRequest)
		return
	}
	sess := &Session{
		UserName:    user_id,
		SessionData: chats,
	}
	sess.SaveSession()
	// 返回成功响应
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(map[string]string{
		"message": "Session saved successfully",
	}); err != nil {
		http.Error(w, "JSON encoding error", http.StatusInternalServerError)
	}
}

// 定义WebSocket处理函数
func websocketHandler(w http.ResponseWriter, r *http.Request) {
	// 配置WebSocket
	upgrader := websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool {
			return true // 允许所有来源，实际应用中应根据需要设置
		},
	}

	// 升级HTTP连接为WebSocket连接
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Printf("Failed to upgrade connection: %v", err)
		return
	}
	defer conn.Close()

	// 设置读取超时
	conn.SetReadDeadline(time.Now().Add(wsReadTimeout))
	conn.SetWriteDeadline(time.Now().Add(wsWriteTimeout))

	// 读取消息
	for {
		var msg NetMessage
		err := conn.ReadJSON(&msg)
		if err != nil {
			if websocket.IsCloseError(err, websocket.CloseNormalClosure) {
				log.Printf("Client closed connection")
			} else {
				log.Printf("Read error: %v", err)
			}
			break
		}

		// 处理消息
		switch msg.Type {
		case "curl":
			func(conn *websocket.Conn, msg NetMessage) {
				fmt.Println("msg:", msg)
				handleCurlRequest(msg.Remote, msg.Id, msg.Data, msg.Headers, msg.Cookie, msg.Usepost, msg.Stream, func(id, reply string) {
					fmt.Println("200:", reply)
					conn.WriteJSON(map[string]string{
						"id":   msg.Id,
						"data": reply,
					})

				})
			}(conn, msg)
			conn.WriteJSON(map[string]any{
				"id":  msg.Id,
				"end": true,
			})
		default:
			// 未知类型，返回错误
			conn.WriteJSON(map[string]string{
				"id":    msg.Id,
				"error": "unknown message type",
			})
		}
	}
}

func handleCurlRequest(remoteHost string, id string, postData map[string]interface{}, headers map[string]interface{}, cookie string, usePost bool, stream bool, callback func(id, reply string)) {
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	req, err := http.NewRequest("", remoteHost, nil)
	if err != nil {
		log.Printf("创建请求失败: %v", err)
		return
	}

	// 设置headers
	for k, v := range headers {
		req.Header.Set(k, v.(string))
	}

	if cookie != "" {
		req.Header.Set("Cookie", cookie)
	}

	// 设置请求方法和body
	if usePost {
		req.Method = http.MethodPost
		contentType := req.Header.Get("Content-Type")
		switch contentType {
		case "application/json":
			jsonBody, _ := json.Marshal(postData)
			req.Body = io.NopCloser(strings.NewReader(string(jsonBody)))
		case "multipart/form-data":
			// 处理multipart/form-data，这里需要更复杂的处理
			// 这里简化处理，实际可能需要使用multipart.NewWriter
			form := make([]byte, 0)
			for key, value := range postData {
				form = append(form, []byte(key+"="+value.(string)+"&")...)
			}
			req.Body = io.NopCloser(strings.NewReader(string(form)))
		default:
			form := make([]byte, 0)
			for key, value := range postData {
				form = append(form, []byte(key+"="+value.(string)+"&")...)
			}
			req.Body = io.NopCloser(strings.NewReader(string(form)))
		}
	} else {
		req.Method = http.MethodGet
	}

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("发送请求失败: %v", err)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		// 读取响应流
		reader := io.Reader(resp.Body)
		scanner := bufio.NewScanner(reader)
		for scanner.Scan() {
			line := scanner.Text()
			callback(id, line)
		}
		if err := scanner.Err(); err != nil {
			log.Printf("读取响应流失败: %v", err)
		}
	} else {
		log.Printf("请求失败，状态码: %d", resp.StatusCode)
		body, _ := io.ReadAll(resp.Body)
		log.Printf("响应内容: %s", string(body))
	}
}

func downloadFileHandler(w http.ResponseWriter, r *http.Request) {
	file_name := path.Base(r.URL.Path)
	fileDir := path.Join(STATIC, "files")
	file_path := path.Join(fileDir, file_name)

	if _, err := os.Stat(file_path); os.IsNotExist(err) {
		http.Error(w, "File not found", http.StatusNotFound)
		return
	}

	w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", file_name))
	w.Header().Set("Content-Type", "application/octet-stream")

	http.ServeFile(w, r, file_path)
}

func getDownURLHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		response := map[string]string{
			"error": "Method Not Allowed",
		}
		json.NewEncoder(w).Encode(response)
		return
	}
	type TMpData struct {
		Data []map[string]interface{} `json:"data"`
	}
	data := &TMpData{}
	err := json.NewDecoder(r.Body).Decode(&data)
	if err != nil {
		http.Error(w, "Invalid JSON data", http.StatusBadRequest)
		return
	}
	fmt.Println("[try down]")

	fileDir := path.Join(STATIC, "files")
	if _, err := os.Stat(fileDir); os.IsNotExist(err) {
		os.MkdirAll(fileDir, 0755)
	}

	tmpName := fmt.Sprintf("%d.xlsx", time.Now().Unix())
	filePath := path.Join(fileDir, tmpName)

	xlsxFile := xlsx.NewFile()
	sheet, err := xlsxFile.AddSheet("Sheet1")
	if err != nil {
		http.Error(w, "Failed to create sheet", http.StatusInternalServerError)
		return
	}

	for i, row := range data.Data {

		keys := []string{}
		for key := range row {
			keys = append(keys, key)
		}
		sort.Slice(keys, func(i, j int) bool {
			return strings.Compare(keys[i], keys[j]) < 0
		})
		newRow := sheet.AddRow()
		if i == 0 {
			for _, key := range keys {
				newCell := newRow.AddCell()
				newCell.SetStyle(&xlsx.Style{
					Font: xlsx.Font{
						Bold: true,
					},
				})

				newCell.Value = key
			}
			// fmt.Println(strings.Join(keys, "\t"))
			newRow = sheet.AddRow()
		}
		for _, key := range keys {
			newCell := newRow.AddCell()
			value := row[key]
			newCell.Value = fmt.Sprintf("%v", value)
			// fmt.Println(key, " = ", value)
		}
		// fmt.Println("---------------")

	}

	err = xlsxFile.Save(filePath)
	if err != nil {
		http.Error(w, "Failed to save Excel file", http.StatusInternalServerError)
		return
	}

	response := map[string]string{
		"url":  "/down_me/" + tmpName,
		"name": tmpName,
	}
	json.NewEncoder(w).Encode(response)
}

const (
	tempDir  = "/tmp"  // 临时文件存储目录
	cacheDir = "cache" // 代理缓存目录
)

var (
	ErrUnsupportedFileType = errors.New("unsupported file type")
	ErrFileRead            = errors.New("failed to read file")
	ErrFileSave            = errors.New("failed to save file")
	ErrJSONParse           = errors.New("failed to parse JSON")
)

func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		respondError(w, http.StatusBadRequest, "Method Not Allowed")
		return
	}

	multipartReader, err := r.MultipartReader()
	if err != nil {
		respondError(w, http.StatusBadRequest, "Invalid form data")
		return
	}

	for {
		part, err := multipartReader.NextPart()
		if err == io.EOF {
			break
		}
		if err != nil {
			respondError(w, http.StatusBadRequest, "Failed to read part")
			return
		}

		filename := part.FileName()
		if filename == "" {
			respondError(w, http.StatusBadRequest, "No file uploaded")
			return
		}

		ext := strings.ToLower(path.Ext(filename))
		if !isSupportedFileType(ext) {
			respondError(w, http.StatusBadRequest, "Unsupported file type")
			return
		}

		tempFile := path.Join(tempDir, fmt.Sprintf("%d_%s", time.Now().UnixNano(), filename))

		if err := saveFile(part, tempFile); err != nil {
			respondError(w, http.StatusInternalServerError, "Failed to save file")
			return
		}

		var replyData interface{}
		switch ext {
		case ".xlsx":
			replyData, err = processExcelFile(tempFile)
		case ".csv":
			replyData, err = processCSVFile(tempFile)
		case ".txt", ".md":
			replyData, err = processTextFile(tempFile)
		default:
			respondError(w, http.StatusBadRequest, "Unsupported file type")
			return
		}

		if err != nil {
			respondError(w, http.StatusInternalServerError, "Failed to process file")
			return
		}

		respondJSON(w, http.StatusOK, map[string]interface{}{
			"data": replyData,
			"name": filename,
		})

		os.Remove(tempFile)
		return
	}

	respondError(w, http.StatusBadRequest, "No file uploaded")
}

func isSupportedFileType(ext string) bool {
	return ext == ".txt" || ext == ".md" || ext == ".xlsx" || ext == ".csv"
}

func saveFile(part *multipart.Part, tempFile string) error {
	file, err := os.Create(tempFile)
	if err != nil {
		return fmt.Errorf("failed to create file: %v", err)
	}
	defer file.Close()

	_, err = io.Copy(file, part)
	if err != nil {
		return fmt.Errorf("failed to save file: %v", err)
	}

	return nil
}

func processExcelFile(filePath string) ([]map[string]interface{}, error) {
	f, err := xlsx.OpenFile(filePath)
	if err != nil {
		return nil, fmt.Errorf("failed to open excel file: %v", err)
	}

	var replyData []map[string]interface{}
	if len(f.Sheets) == 0 {
		return nil, fmt.Errorf("failed to open excel file: %v", err)
	}
	sheet := f.Sheets[0]
	rows := sheet.Rows

	for no, row := range rows {
		if no == 0 {
			continue
		}

		item := make(map[string]interface{})
		for i, cell := range row.Cells {
			if i == 0 {
				item["id"] = no - 1
			} else {
				item[strings.TrimSpace(rows[0].Cells[i].Value)] = strings.TrimSpace(cell.Value)
			}
		}
		replyData = append(replyData, item)
	}
	return replyData, nil
}

// ParseCSV 读取 CSV 文件并返回一个 []map[string]any 结构
func processCSVFile(filePath string) ([]map[string]any, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	reader := csv.NewReader(file)
	// 自动检测 CSV 的分隔符和引号字符
	_, err = reader.Read()
	if err != nil {
		return nil, err
	}
	// reader.R
	reader.FieldsPerRecord = -1 // 允许每行的字段数不同

	var result []map[string]any
	// 读取标题行
	headers, err := reader.Read()
	if err != nil {
		return nil, err
	}

	// 读取数据行
	for {
		record, err := reader.Read()
		if err != nil {
			break
		}

		row := make(map[string]any)
		for i, header := range headers {
			if i < len(record) {
				// 尝试将值转换为整数，如果可能的话
				if value, err := strconv.Atoi(record[i]); err == nil {
					row[header] = value
				} else {
					row[header] = record[i]
				}
			}
		}
		result = append(result, row)
	}

	return result, nil
}

func processTextFile(filePath string) (string, error) {
	content, err := os.ReadFile(filePath)
	if err != nil {
		return "", fmt.Errorf("failed to read text file: %v", err)
	}

	return string(content), nil
}

func respondJSON(w http.ResponseWriter, status int, data interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	if err := json.NewEncoder(w).Encode(data); err != nil {
		log.Printf("Failed to encode JSON response: %v", err)
	}
}

func respondError(w http.ResponseWriter, status int, message string) {
	respondJSON(w, status, map[string]string{
		"error": message,
	})
}

func listAgentHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		respondError(w, http.StatusBadRequest, "Method Not Allowed")
		return
	}

	if _, err := os.Stat(agentPath); os.IsNotExist(err) {
		os.MkdirAll(agentPath, 0755)
	}

	var res []map[string]string
	files, err := os.ReadDir(agentPath)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "Failed to read cache directory")
		return
	}

	for _, file := range files {
		if !file.IsDir() && strings.HasSuffix(file.Name(), ".json") {
			filePath := path.Join(agentPath, file.Name())
			content, err := os.ReadFile(filePath)
			if err != nil {
				log.Printf("Failed to read file %s: %v", filePath, err)
				continue
			}

			var one map[string]interface{}
			if err := json.Unmarshal(content, &one); err != nil {
				log.Printf("Failed to parse JSON file %s: %v", filePath, err)
				continue
			}

			typeName, ok := one["type"].(string)
			if !ok {
				continue
			}

			name := file.Name()
			if nameJson, ok := one["name"].(string); ok && nameJson != "" {
				name = nameJson
			}

			res = append(res, map[string]string{
				"value": name,
				"label": name,
				"type":  typeName,
			})
		}
	}

	respondJSON(w, http.StatusOK, res)
}

func loadAgent(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		respondError(w, http.StatusBadRequest, "Method Not Allowed")
		return
	}
	w.Header().Set("Content-Type", "application/json")
	type SS struct {
		Name string `json:"name"`
	}
	s := &SS{}
	json.NewDecoder(r.Body).Decode(s)
	d := filepath.Join(agentPath, s.Name+".json")
	buf, err := os.ReadFile(d)
	if err == nil {
		w.Write(buf)
	} else {
		w.Write([]byte(`{"error":"no name provided"}`))
	}

}

func delAgent(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		respondError(w, http.StatusBadRequest, "Method Not Allowed")
		return
	}
	w.Header().Set("Content-Type", "application/json")
	type SS struct {
		Name string `json:"name"`
	}
	s := &SS{}
	json.NewDecoder(r.Body).Decode(s)
	d := filepath.Join(agentPath, s.Name+".json")
	_, err := os.ReadFile(d)
	if err == nil {
		os.Remove(d)
	} else {
		w.Write([]byte(`{"error":"no name provided"}`))
	}
}

func saveAgent(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodPost {
		respondError(w, http.StatusBadRequest, "Method Not Allowed")
		return
	}
	w.Header().Set("Content-Type", "application/json")

	s := map[string]any{}
	if err := json.NewDecoder(r.Body).Decode(&s); err == nil {
		if name, ok := s["name"]; ok {
			d := filepath.Join(agentPath, name.(string)+".json")
			ff := regexp.MustCompile(`^[a-zA-Z0-9\-\_\.]+$`)

			if ff.Match([]byte(name.(string))) {
				delete(s, "data")
				if ebuf, err := json.Marshal(s); err == nil {
					os.WriteFile(d, ebuf, os.ModePerm)
					w.Write([]byte(`{"status":"ok"}`))
				} else {
					w.Write([]byte(`{"error":"json to buf err"}`))
				}

			} else {
				w.Write([]byte(`{"err":"invalid name:` + name.(string) + `"}`))
			}

		} else {
			w.Write([]byte(`{"err":"must have a name"}`))
		}

	} else {
		w.Write([]byte(`{"error":"not valid json"}`))
	}

}

type Agent struct {
	BatchSize int      `json:"batch_size"`
	Example   string   `json:"example"`
	Target    string   `json:"target"`
	Type      string   `json:"type"`
	Points    []string `json:"points"`
	Name      string   `json:"name"`
	ModelAPI  string   `json:"model_api"`
	ModelNmae string   `json:"model"`
	Threads   int      `json:"threads"`
	Data      []any    `json:"data"`
	UseJson   bool     `json:"useJson"`
}

func getPreivew(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		respondError(w, http.StatusBadRequest, "Method Not Allowed")
		return
	}

	agent := &Agent{}
	json.NewDecoder(r.Body).Decode(agent)
	if agent.Name == "" {
		w.Write([]byte(`{"error":"must have a name"}`))
	}
	if strings.TrimSpace(agent.Target) == "" {
		w.Write([]byte(`{"error":"must have a target"}`))
	}
	template := "# " + strings.TrimSpace(agent.Target) + ":\n\n"
	for no, point := range agent.Points {
		template += " " + fmt.Sprintf("%d. %s", no+1, point) + ".\n"
	}

	if agent.UseJson {
		template += fmt.Sprintf("%d. %s", len(agent.Points)+1, "请按照要求和数据的json格式.\n")
	}

	if strings.TrimSpace(agent.Example) != "" {
		template += "\n# 参考例子:\n\n" + strings.TrimSpace(agent.Example) + "\n\n"
	}
	batchs := []string{}
	if len(agent.Data) > 0 {
		template += "\n# 数据如下:\n\n"
		templateCopy := template
		for no, data := range agent.Data {
			if mapData, ok := data.(map[string]any); ok {
				if _, ok := mapData["id"]; !ok {
					mapData["id"] = no
				}
				if line, err := json.Marshal(mapData); err == nil {
					templateCopy += fmt.Sprintf("%s\n", string(line))
				}
			} else {
				one := fmt.Sprintf("%v\n", data)
				if !strings.Contains(one, "id:") {
					one = fmt.Sprintf("id: %d\n", no) + one
				}
				templateCopy += fmt.Sprintf("%s\n\n", one)
			}
			if no == agent.BatchSize-1 {
				batchs = append(batchs, templateCopy)
				templateCopy = template
			}
		}
		batchs = append(batchs, templateCopy)

	} else {
		batchs = append(batchs, template)
	}
	w.Header().Set("Content-Type", "application/json")
	dd := map[string]any{
		"data": batchs,
	}
	json.NewEncoder(w).Encode(dd)
}
